package copyengine.ui.tooltips
{
	import copyengine.utils.GeneralUtils;
	import copyengine.utils.tick.GlobalTick;
	
	import flash.display.Stage;
	import flash.events.MouseEvent;

	public final class CEToolTipsWarp
	{
		private var source:ICETooltipsSource;
		private var tooltips:ICEToolTips;

		private var delayTick:int;
		private var isShowTips:Boolean;

		private var stage:Stage;
		private var lastTickMousePosX:Number;
		private var lastTickMousePosY:Number;

		private static const SHOW_TIPS_HOLD_TICK:int = 4;

		public function CEToolTipsWarp()
		{
		}

		public function initialize(_source:ICETooltipsSource, _tooltips:ICEToolTips, _stage:Stage):void
		{
			source = _source;
			tooltips = _tooltips;
			tooltips.getContainer().visible = false;
			stage = _stage;

			addListener();
		}

		public function dispose():void
		{
			removeListener();

			tooltips.dispose();
			GeneralUtils.removeTargetFromParent(tooltips.getContainer());
			tooltips = null;
			source = null;
		}

		public function getSource():ICETooltipsSource
		{
			return source;
		}

		private function addListener():void
		{
			GeneralUtils.addTargetEventListener(source.getContainer(), MouseEvent.ROLL_OVER, onRollOver);
			GeneralUtils.addTargetEventListener(source.getContainer(), MouseEvent.ROLL_OUT, onRollOut);
		}

		private function removeListener():void
		{
			GeneralUtils.removeTargetEventListener(source.getContainer(), MouseEvent.ROLL_OVER, onRollOver);
			GeneralUtils.removeTargetEventListener(source.getContainer(), MouseEvent.ROLL_OUT, onRollOut);
			GlobalTick.instance.removeTickNodeByFunction(onTipsShowTick);
		}

		private function showTips():void
		{
			delayTick = 0;
			isShowTips = true;

			tooltips.mouseOnMove(stage.mouseX, stage.mouseY);
			tooltips.getContainer().visible = true;
			tooltips.show(source);

			lastTickMousePosX = stage.mouseX;
			lastTickMousePosY = stage.mouseY;
		}

		private function hideTips():void
		{
			delayTick = 0;
			isShowTips = false;
			GlobalTick.instance.removeTickNodeByFunction(onTipsShowTick);
			tooltips.getContainer().visible = false;
			tooltips.hide();
			lastTickMousePosX = int.MIN_VALUE;
			lastTickMousePosY = int.MIN_VALUE;
		}

		private function onRollOver(e:MouseEvent):void
		{
			GlobalTick.instance.callLaterAfterTickCount(onTipsShowTick, 1, int.MAX_VALUE);
		}
		
		private function onRollOut(e:MouseEvent):void
		{
			hideTips();
		}

		private function onTipsShowTick():void
		{
			if (isShowTips)
			{
				onTickShowTipsLogic();
			}
			else
			{
				onTickHideTipsLogic();
			}
		}

		private function onTickShowTipsLogic():void
		{
			if (isMouseInTarget())
			{
				if (isMouseMove())
				{
					tooltips.mouseOnMove(stage.mouseX, stage.mouseY);
				}
				lastTickMousePosX = stage.mouseX;
				lastTickMousePosY = stage.mouseY;
			}
			else
			{
				hideTips();
			}
		}

		private function onTickHideTipsLogic():void
		{
			if (isMouseInTarget())
			{
				delayTick++;
			}
			else
			{
				GlobalTick.instance.removeTickNodeByFunction(onTipsShowTick);
			}
			if (delayTick >= SHOW_TIPS_HOLD_TICK)
			{
				showTips();
			}
		}

		private function isMouseInTarget():Boolean
		{
			return source.getContainer().visible &&
				source.getContainer().hitTestPoint(source.getContainer().stage.mouseX,
												   source.getContainer().stage.mouseY);
		}

		private function isMouseMove():Boolean
		{
			if (stage.mouseX == lastTickMousePosX && stage.mouseY == lastTickMousePosY)
			{
				return false;
			}
			else
			{
				return true;
			}
		}

	}
}